package com.zliblike_platform.service.impl;

import com.zliblike_platform.dto.BookDownloadDTO;
import com.zliblike_platform.dto.BookUploadDTO;
import com.zliblike_platform.dto.FormatConversionDTO;
import com.zliblike_platform.entity.Book;
import com.zliblike_platform.entity.DownloadHistory;
import com.zliblike_platform.entity.User;
import com.zliblike_platform.mapper.BookMapper;
import com.zliblike_platform.mapper.UserMapper;
import com.zliblike_platform.service.BookService;
import com.zliblike_platform.service.DownloadHistoryService;
import com.zliblike_platform.vo.BookInfoVO;
import com.zliblike_platform.vo.BookUploadResultVO;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 书籍服务实现类
 */
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookMapper bookMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private DownloadHistoryService downloadHistoryService;
    
    @Value("${minio.book.storage-path}")
    private String bookStoragePath;
    
    @Value("${book.formats}")
    private String formatsStr;
    
    private List<String> formats;
    
    @Override
    public List<String> getFormats() {
        if (formats == null) {
            formats = Arrays.asList(formatsStr.split(","));
        }
        return formats;
    }
    
    @Override
    public BookInfoVO getBookInfo(Long bookId) {
        Book book = bookMapper.selectById(bookId);
        if (book == null) {
            return null;
        }
        
        BookInfoVO bookInfoVO = new BookInfoVO();
        bookInfoVO.setBookId(book.getBookId());
        bookInfoVO.setTitle(book.getTitle());
        bookInfoVO.setAuthor(book.getAuthor());
        bookInfoVO.setIsbn10(book.getIsbn10());
        bookInfoVO.setIsbn13(book.getIsbn13());
        bookInfoVO.setPublisher(book.getPublisher());
        bookInfoVO.setPubYear(book.getPubYear());
        bookInfoVO.setLanguage(book.getLanguage());
        
        // 获取可用格式
        List<String> formats = bookMapper.selectAvailableFormats(bookId);
        bookInfoVO.setAvailableFormats(formats);
        
        // 设置其他属性
        bookInfoVO.setPopularity(book.getPopularityScore());
        bookInfoVO.setCoverUrl("/api/book/" + bookId + "/cover");
        
        return bookInfoVO;
    }
    
    @Override
    @Transactional
    public void downloadBook(Long userId, BookDownloadDTO downloadDTO, HttpServletResponse response) {
        // 检查下载权限
        if (!checkDownloadPermission(userId)) {
            try {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "超出今日下载限额");
                return;
            } catch (IOException e) {
                throw new RuntimeException("发送响应错误", e);
            }
        }
        
        // 获取书籍信息
        Book book = bookMapper.selectById(downloadDTO.getBookId());
        if (book == null) {
            try {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, "书籍不存在");
                return;
            } catch (IOException e) {
                throw new RuntimeException("发送响应错误", e);
            }
        }
        
        // 检查请求的格式是否可用
        List<String> availableFormats = getAvailableFormats(downloadDTO.getBookId());
        if (!availableFormats.contains(downloadDTO.getFormat())) {
            try {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "请求的格式不可用");
                return;
            } catch (IOException e) {
                throw new RuntimeException("发送响应错误", e);
            }
        }
        
        // 构建文件路径
        String filePath = String.format("%s/%d/%s.%s", 
                bookStoragePath, 
                downloadDTO.getBookId(), 
                book.getTitle().replaceAll("[^\\w]", "_"), 
                downloadDTO.getFormat().toLowerCase());
        
        Path path = Paths.get(filePath);
        
        try {
            // 设置响应头
            response.setContentType(getContentType(downloadDTO.getFormat()));
            response.setHeader("Content-Disposition", "attachment; filename=\"" + book.getTitle() + "." + downloadDTO.getFormat().toLowerCase() + "\"");
            
            // 写入文件流到响应
            try (InputStream inputStream = Files.newInputStream(path);
                 OutputStream outputStream = response.getOutputStream()) {
                
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }
            
            // 记录下载历史
            DownloadHistory history = new DownloadHistory();
            history.setUserId(userId);
            history.setBookId(downloadDTO.getBookId());
            history.setDownloadFormat(downloadDTO.getFormat());
            history.setDownloadTime(new Date());
            downloadHistoryService.createDownloadHistory(history);
            
            // 增加书籍受欢迎度
            increasePopularity(downloadDTO.getBookId(), 4);
            
        } catch (IOException e) {
            throw new RuntimeException("下载书籍失败", e);
        }
    }
    
    @Override
    public List<String> getAvailableFormats(Long bookId) {
        return bookMapper.selectAvailableFormats(bookId);
    }
    
    @Override
    public Long requestFormatConversion(Long userId, FormatConversionDTO conversionDTO) {
        // 这里是格式转换的实现，调用外部API
        // 具体细节需要根据实际集成的外部服务来确定
        // 返回一个转换请求ID
        return 0L;
    }
    
    @Override
    public boolean checkDownloadPermission(Long userId) {
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            return false;
        }
        
        // 获取今日下载次数
        int todayDownloads = downloadHistoryService.getTodayDownloadCount(userId);
        
        // 检查是否超过限制
        return todayDownloads < user.getDailyDownloadLimit();
    }
    
    @Override
    public void increasePopularity(Long bookId, Integer score) {
        bookMapper.updatePopularityScore(bookId, score);
    }
    
    @Override
    @Transactional
    public BookUploadResultVO uploadBook(Long userId, BookUploadDTO uploadDTO) {
        BookUploadResultVO resultVO = new BookUploadResultVO();
        
        try {
            // 验证上传数据
            if (uploadDTO.getBookFile() == null || uploadDTO.getBookFile().isEmpty()) {
                resultVO.setStatus("失败");
                resultVO.setMessage("电子书文件不能为空");
                return resultVO;
            }
            
            // 检查文件格式
            String fileExtension = FilenameUtils.getExtension(uploadDTO.getBookFile().getOriginalFilename()).toUpperCase();
            if (!getFormats().contains(fileExtension)) {
                resultVO.setStatus("失败");
                resultVO.setMessage("不支持的文件格式：" + fileExtension + "，支持的格式：" + String.join(", ", getFormats()));
                return resultVO;
            }
            
            // 检查ISBN是否已存在
            if (StringUtils.hasText(uploadDTO.getIsbn13()) && isbnExists(uploadDTO.getIsbn13())) {
                resultVO.setStatus("失败");
                resultVO.setMessage("ISBN-13已存在");
                return resultVO;
            }
            
            if (StringUtils.hasText(uploadDTO.getIsbn10()) && isbnExists(uploadDTO.getIsbn10())) {
                resultVO.setStatus("失败");
                resultVO.setMessage("ISBN-10已存在");
                return resultVO;
            }
            
            // 创建书籍实体
            Book book = new Book();
            book.setTitle(uploadDTO.getTitle());
            book.setAuthor(uploadDTO.getAuthor());
            book.setIsbn10(uploadDTO.getIsbn10());
            book.setIsbn13(uploadDTO.getIsbn13());
            book.setPublisher(uploadDTO.getPublisher());
            book.setPubYear(uploadDTO.getPubYear());
            book.setLanguage(uploadDTO.getLanguage());
            book.setFileFormat(fileExtension);
            book.setFileSizeMb(new BigDecimal(uploadDTO.getBookFile().getSize()).divide(new BigDecimal(1048576), 2, RoundingMode.HALF_UP));
            book.setUploaderId(userId);
            book.setStatus("待审核");
            book.setPopularityScore(0L);
            book.setCreatedAt(new Date());
            
            // 处理封面图片
            if (uploadDTO.getCoverFile() != null && !uploadDTO.getCoverFile().isEmpty()) {
                book.setCoverImage(uploadDTO.getCoverFile().getBytes());
            }
            
            // 插入数据库
            bookMapper.insert(book);
            
            // 保存电子书文件
            saveBookFile(book.getBookId(), uploadDTO.getBookFile(), fileExtension.toLowerCase());
            
            // 填充返回结果
            resultVO.setBookId(book.getBookId());
            resultVO.setTitle(book.getTitle());
            resultVO.setFileFormat(book.getFileFormat());
            resultVO.setFileSizeBytes(uploadDTO.getBookFile().getSize());
            resultVO.setCoverUrl("/api/book/" + book.getBookId() + "/cover");
            resultVO.setStatus("成功");
            resultVO.setMessage("上传成功");
            
            return resultVO;
            
        } catch (Exception e) {
            resultVO.setStatus("失败");
            resultVO.setMessage("上传失败：" + e.getMessage());
            return resultVO;
        }
    }
    
    @Override
    public boolean isbnExists(String isbn) {
        return bookMapper.selectByIsbn(isbn) != null;
    }
    
    @Override
    public List<BookInfoVO> getPopularBooks(Integer limit) {
        List<Book> books = bookMapper.selectPopularBooks(limit);
        return books.stream()
                .map(this::convertToBookInfoVO)
                .toList();
    }
    
    @Override
    public List<BookInfoVO> getPopularBooksByCategory(Long categoryId, Integer limit) {
        List<Book> books = bookMapper.selectPopularBooksByCategory(categoryId, limit);
        return books.stream()
                .map(this::convertToBookInfoVO)
                .toList();
    }
    
    /**
     * 将Book实体转换为BookInfoVO
     * @param book 书籍实体
     * @return 书籍信息VO
     */
    private BookInfoVO convertToBookInfoVO(Book book) {
        BookInfoVO bookInfoVO = new BookInfoVO();
        bookInfoVO.setBookId(book.getBookId());
        bookInfoVO.setTitle(book.getTitle());
        bookInfoVO.setAuthor(book.getAuthor());
        bookInfoVO.setIsbn10(book.getIsbn10());
        bookInfoVO.setIsbn13(book.getIsbn13());
        bookInfoVO.setPublisher(book.getPublisher());
        bookInfoVO.setPubYear(book.getPubYear());
        bookInfoVO.setLanguage(book.getLanguage());
        
        // 获取可用格式
        List<String> formats = bookMapper.selectAvailableFormats(book.getBookId());
        bookInfoVO.setAvailableFormats(formats);
        
        // 设置其他属性
        bookInfoVO.setPopularity(book.getPopularityScore());
        bookInfoVO.setCoverUrl(book.getCoverUrl() != null ? book.getCoverUrl() : "/api/book/" + book.getBookId() + "/cover");
        
        return bookInfoVO;
    }
    
    /**
     * 保存电子书文件
     * 
     * @param bookId 书籍ID
     * @param file 文件
     * @param fileExtension 文件扩展名
     * @throws IOException IO异常
     */
    private void saveBookFile(Long bookId, MultipartFile file, String fileExtension) throws IOException {
        // 创建目录
        String dirPath = bookStoragePath + "/" + bookId;
        File dir = new File(dirPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        // 保存文件
        String filePath = dirPath + "/" + bookId + "." + fileExtension;
        file.transferTo(new File(filePath));
    }
    
    /**
     * 根据文件格式获取Content-Type
     * 
     * @param format 文件格式
     * @return Content-Type
     */
    private String getContentType(String format) {
        switch (format.toUpperCase()) {
            case "PDF":
                return "application/pdf";
            case "EPUB":
                return "application/epub+zip";
            case "MOBI":
                return "application/x-mobipocket-ebook";
            default:
                return "application/octet-stream";
        }
    }

    @Override
    public Integer convertFormat(Integer bookId, String targetFormat) {
        // 检查书籍是否存在
        Book book = bookMapper.selectById(Long.valueOf(bookId));
        if (book == null) {
            return null;
        }
        
        // 检查目标格式是否有效
        if (!Arrays.asList("EPUB", "MOBI", "PDF").contains(targetFormat)) {
            return null;
        }
        
        // 检查书籍当前格式
        String currentFormat = book.getFileFormat();
        if (currentFormat.equals(targetFormat)) {
            // 已经是目标格式，无需转换
            return null;
        }
        
        // TODO: 调用外部Calibre-Web API进行格式转换
        // 这里简化实现，实际应该是异步调用外部服务
        
        // 记录转换任务
        // 实际项目中应该有一个转换任务表
        Integer convertId = 1; // 模拟生成转换任务ID
        
        return convertId;
    }

    @Override
    public String getConvertStatus(Integer convertId) {
        // TODO: 实际应该查询转换任务表获取状态
        return "processing"; // 模拟返回状态
    }

    @Override
    public Integer getConvertedBookId(Integer convertId) {
        // TODO: 实际应该查询转换任务表获取转换后的书籍ID
        return null; // 表示转换尚未完成
    }

    @Override
    public List<String> getAvailableFormats(Integer bookId) {
        // 实际应该查询相同ISBN但不同格式的书籍
        List<String> formats = new ArrayList<>();
        Book book = bookMapper.selectById(Long.valueOf(bookId));
        if (book != null) {
            formats.add(book.getFileFormat());
            // TODO: 查询其他格式
        }
        return formats;
    }

    @Override
    public void updatePopularity(Integer bookId, String actionType) {
        int scoreIncrement = 0;
        
        // 根据不同行为设置不同的分数增量
        switch (actionType) {
            case "view":
                scoreIncrement = 1;
                break;
            case "read":
                scoreIncrement = 2;
                break;
            case "download":
                scoreIncrement = 4;
                break;
            case "addToList":
                scoreIncrement = 4;
                break;
            case "comment":
                scoreIncrement = 1;
                break;
            case "rate":
                scoreIncrement = 3;
                break;
            default:
                return;
        }
        
        // 更新书籍受欢迎度
        bookMapper.incrementPopularity(Long.valueOf(bookId), scoreIncrement);
    }

    @Override
    public List<BookInfoVO> getMostPopularBooks(int page, int size) {
        int offset = (page - 1) * size;
        return bookMapper.selectMostPopularBooks(offset, size);
    }
} 